﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JFTest.Nlog;

namespace JFTest.CommunicationService
{
    public class TCPIPClentBase : IDisposable
    {
        /// <summary>
        /// TCP/IP通信基类
        /// </summary>
        #region 字段/属性

        protected TcpClient _tcpClient;
        protected NetworkStream _networkStream;
        protected CancellationTokenSource _cts;

        protected bool _disposed = false;

        protected string Name;

        /// <summary>
        /// 接收缓冲区大小（默认4KB）
        /// </summary>
        public int ReceiveBufferSize { get; set; } = 4096;

        /// <summary>
        /// 自动重连间隔（毫秒，0表示禁用）
        /// </summary>
        public int ReconnectInterval { get; set; } = 5000;

        protected string ip;
        protected int port;

        /// <summary>
        /// 当前连接状态
        /// </summary>
        public bool IsConnected => _tcpClient?.Connected ?? false;

        /// <summary>
        /// 远端终结点信息
        /// </summary>
        public EndPoint RemoteEndPoint => _tcpClient?.Client.RemoteEndPoint;

        /// <summary>
        /// 最大重连次数（0 表示无限重连）
        /// </summary>
        public int MaxReconnectAttempts { get; set; } = 10;

        #endregion

        #region 事件定义

        /// <summary>
        /// 数据接收事件
        /// </summary>
        public event Action<byte[]> DataReceived;

        /// <summary>
        /// 连接状态变化事件
        /// </summary>
        public event Action<bool> ConnectionStateChanged;

        /// <summary>
        /// 错误发生事件
        /// </summary>
        public event Action<Exception> ErrorOccurred;

        #endregion

        #region 构造函数/初始化

        /// <summary>
        /// 客户端模式初始化
        /// </summary>
        public void InitializeClient()
        {
            _tcpClient = new TcpClient { ReceiveBufferSize = ReceiveBufferSize };
            
        }


        #endregion

        #region 连接管理

        /// <summary>
        /// 连接到远程主机（客户端模式）
        /// </summary>
        public virtual async Task ConnectAsync(string host, int port)
        {
         
            if (IsConnected) return;

            try
            {
                _cts = new CancellationTokenSource();
                await _tcpClient.ConnectAsync(host, port);
                _networkStream = _tcpClient.GetStream();
                OnConnectionStateChanged(true);
                StartReceiving();
            }
            catch (Exception ex)
            {
                OnErrorOccurred(ex);
                throw;
            }
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public virtual void Disconnect()
        {
            if (!IsConnected) return;

            try
            {
                _cts?.Cancel();
                _networkStream?.Close();
                _tcpClient?.Close();
                OnConnectionStateChanged(false);
                
            }
            catch (Exception ex)
            {
                OnErrorOccurred(ex);
                throw;
            }
        }

        #endregion

        #region 数据收发

        /// <summary>
        /// 发送字节数据
        /// </summary>
        public async Task SendBytesAsync(byte[] data)
        {
            if (!IsConnected) throw new InvalidOperationException("未建立连接");

            try
            {
                await _networkStream.WriteAsync(data, 0, data.Length, _cts.Token);
                await _networkStream.FlushAsync(_cts.Token);
            }
            catch (Exception ex)
            {
                OnErrorOccurred(ex);
                ColoredOutput.WriteOperationLine(PresetColor.Red,$"{Name}错误"+ex.Message);
                throw new Exception (ex.Message);
            }
        }

        /// <summary>
        /// 发送字符串数据（UTF8编码）
        /// </summary>
        public async Task<bool> SendStringAsync(string message)
        {
            try
            {
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                await SendBytesAsync(buffer);
                return true;
            }
            catch(Exception e)
            {
                ColoredOutput.WriteStatusLine(PresetColor.Red, e.Message);
                return false;
            }
        }

        protected void StartReceiving()
        {
            if (_cts is null)
                _cts = new CancellationTokenSource();
            Task.Run(async () =>
            {
                byte[] buffer = new byte[ReceiveBufferSize];

                while (IsConnected && !_cts.IsCancellationRequested)
                {
                    try
                    {
                        int bytesRead = await _networkStream.ReadAsync(buffer, 0, buffer.Length, _cts.Token);
                        if (bytesRead == 0) break;

                        byte[] receivedData = new byte[bytesRead];
                        Buffer.BlockCopy(buffer, 0, receivedData, 0, bytesRead);
                        OnDataReceived(receivedData);
                    }
                    catch (Exception ex)
                    {
                        if (!_cts.IsCancellationRequested)
                            OnErrorOccurred(ex);
                        break;
                    }
                }
                Disconnect();
            }, _cts.Token);
        }

        #endregion

        #region 事件触发

        protected virtual void OnDataReceived(byte[] data)
        {
            DataReceived?.Invoke(data);
        }

        protected virtual void OnConnectionStateChanged(bool isConnected)
        {
            ConnectionStateChanged?.Invoke(isConnected);
        }

        protected virtual void OnErrorOccurred(Exception ex)
        {
            ErrorOccurred?.Invoke(ex);
        }

        #endregion

        #region 自动重连

        protected  async void StartReconnectMonitor()
        {
            if (_cts != null && !_cts.IsCancellationRequested)
                _cts.Cancel(); // 取消之前的重连任务

            _cts = new CancellationTokenSource();
            var token = _cts.Token;

            await Task.Run(async () =>
            {
                int attemptCount = 0; // 修复计数器初始值
                try
                {
                    while (true)
                    {
                        if (!IsConnected)
                        {
                            try
                            {
                                attemptCount++; // 每次尝试递增
                                ColoredOutput.WriteStatusLine(PresetColor.Red, $"{Name}检测到断开连接，尝试重新连接...");
                                ColoredOutput.WriteOperationLine(PresetColor.Black, $"{Name}第{attemptCount}次重连");
                                await AttemptReconnect();

                                // 重连成功重置计数器
                                attemptCount = 0; // +++ 修复2：成功时重置计数 +++
                            }
                            catch (Exception ex)
                            {
                                ColoredOutput.WriteStatusLine(PresetColor.Red, $"{Name}重连失败: {ex.Message}");
                                // +++ 修复3：使用MaxReconnectAttempts配置 +++
                                if (MaxReconnectAttempts > 0 && attemptCount >= MaxReconnectAttempts)
                                {
                                    ColoredOutput.WriteStatusLine(PresetColor.Red,
                                        $"{Name}重连失败已达{MaxReconnectAttempts}次，停止重连。");
                                    break;
                                }
                            }
                            await Task.Delay(10000);
                        }
                        else
                        {
                            await Task.Delay(10000);
                        }
                    }
                }
                catch (TaskCanceledException) { }
            });
        }

        private async Task AttemptReconnect()
        {
            try
            {
                
                _tcpClient = new TcpClient();
                await _tcpClient.ConnectAsync(ip, port);
                _networkStream = _tcpClient.GetStream();

                // +++ 修复1：重连后必须重启数据接收任务 +++
                OnConnectionStateChanged(true);
                StartReceiving();
                // +++++++++++++++++++++++++++++++++++++++

                ColoredOutput.WriteStatusLine(PresetColor.Green, $"{Name}重连成功！");
            }
            catch
            {
                throw;
            }
        }

        private void StopReconnectMonitor()
        {
            if (_cts != null && !_cts.IsCancellationRequested)
            {
                _cts.Cancel();
                _cts.Dispose();
                _cts = null; // 避免重复使用旧的 CancellationTokenSource
            }
        }




        #endregion

        #region 资源释放

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed) return;

            if (disposing)
            {
                StopReconnectMonitor();
                Disconnect();
                _networkStream?.Dispose();
                _tcpClient?.Dispose();
                _cts?.Dispose();
            }

            _disposed = true;
        }



        #endregion
    }
}
